<template>
  <div>
    <div class="main-body-content">
      <div
        style="
          display: flex;
          align-items: flex-start;
          justify-content: space-around;
          background-color: #f5faff;
        "
      >
        <div
          style="
            width: 40%;
            border-radius: 5px;
            height: calc(50vh + 125px);
            padding: 10px;
          "
        >
          <div
            style="
              height: 100px;
              color: #000;
              background-color: #f5faff;
              padding-top: 40px;
              padding-left: 30px;
              letter-spacing: 5px;
              font: 1.8em sans-serif;
              font-weight: 600;
              border-bottom: 1px solid #ddd;
            "
          >
            所有群聊
          </div>
          <div class="user-list-box">
            <div class="user-list-box">
              <div
                class="user-list-item"
                v-for="item in groups"
                @click="load(item.id, item.name)"
              >
                <img
                  :src="item.avatar"
                  style="width: 30px; height: 30px; border-radius: 50%"
                />
                <span style="flex: 1; margin-left: 10px">{{ item.name }}</span>
              </div>
            </div>
          </div>
        </div>

        <!--  中间部分  -->
        <div
          style="
            width: 60%;
            border-radius: 5px;
            background-color: #f5faff;
            padding: 10px;
            color: #000;
          "
        >
          <div
            style="
              padding: 50px 0px 10px 45px;
              border-bottom: 1px solid #ddd;
              color: #000;
              background-color: #f5faff;
              height: 100px;
              top: 10px;
              letter-spacing: 1px;
              font: 1.5em sans-serif;
              font-weight: 500;
            "
          >
            {{ groupName }}
          </div>
          <div class="im-message-box">
            <div class="im-message-box">
              <div v-for="item in messages" :key="item.id">
                <!--  右边的气泡 -->
                <div
                  style="
                    display: flex;
                    flex-direction: row-reverse;
                    align-items: flex-start;
                  "
                  v-if="item.fromuser === user.name"
                >
                  <img
                    :src="item.fromavatar"
                    alt=""
                    style="
                      width: 40px;
                      height: 40px;
                      border-radius: 50%;
                      margin-left: 10px;
                    "
                  />
                  <div
                    class="im-message im-message-right"
                    v-html="item.content"
                    v-if="item.type === 'text'"
                  ></div>
                  <div
                    class="im-message"
                    style="padding: 0"
                    v-if="item.type === 'img'"
                  >
                    <!-- 注意  el-image 的load函数必须加上，否则无法触发滚动条到最底端 -->
                    <el-image
                      style="width: 100px"
                      :src="item.content"
                      alt=""
                      :preview-src-list="[item.content]"
                      @load="scrollToBottom"
                    ></el-image>
                  </div>
                  <div
                    class="im-message im-message-right im-message-download"
                    v-if="item.type === 'file'"
                    @click="download(item.content)"
                  >
                    <div>
                      <i class="iconfont icon-weibiaoti--"></i>
                      <span>{{
                        item.content.substring(item.content.indexOf("-") + 1)
                      }}</span>
                    </div>
                  </div>
                  <div
                    class="im-message im-message-right im-message-download"
                    v-if="item.type === 'voice'"
                    @click="download(item.content)"
                  >
                    <div>
                      <i class="iconfont icon-yuyin"></i>
                      <span>这是一条语音，点击收听</span>
                    </div>
                  </div>
                </div>

                <!--  左边的气泡 -->
                <div style="display: flex; align-items: flex-start" v-else>
                  <img
                    :src="item.fromavatar"
                    alt=""
                    style="
                      width: 40px;
                      height: 40px;
                      border-radius: 50%;
                      margin-right: 10px;
                    "
                  />
                  <div style="width: 100%">
                    <div style="color: #888; font-size: 12px; width: 50%">
                      {{
                        item.fromuser?.substring(item.fromuser.indexOf("_") + 1)
                      }}
                    </div>
                    <div
                      class="im-message im-message-left"
                      v-html="item.content"
                      v-if="item.type === 'text'"
                    ></div>
                    <div
                      class="im-message"
                      style="padding: 0"
                      v-if="item.type === 'img'"
                    >
                      <!-- 注意  el-image 的load函数必须加上，否则无法触发滚动条到最底端 -->
                      <el-image
                        style="width: 100px"
                        :src="item.content"
                        alt=""
                        :preview-src-list="[item.content]"
                        @load="scrollToBottom"
                      ></el-image>
                    </div>
                    <div
                      class="im-message im-message-left im-message-download"
                      v-if="item.type === 'file'"
                      @click="download(item.content)"
                    >
                      <div>
                        <i class="iconfont icon-weibiaoti--"></i>
                        <span>{{
                          item.content.substring(item.content.indexOf("-") + 1)
                        }}</span>
                      </div>
                    </div>
                    <div
                      class="im-message im-message-right im-message-download"
                      v-if="item.type === 'voice'"
                      @click="download(item.content)"
                    >
                      <div>
                        <i class="iconfont icon-yuyin"></i>
                        <span>这是一条语音，点击收听</span>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>

          <!-- 输入区域 -->
          <div style="position: relative">
            <el-progress
              style="position: absolute; top: -40px; width: 80%"
              v-show="progress > 0"
              :percentage="progress"
              :stroke-width="5"
              status="success"
              class="progress-bar"
            />
            <div
              style="
                position: absolute;
                top: -20px;
                left: 75%;
                width: 80%;
                font-size: 0.3em;
              "
              v-if="progress > 0"
              type="primary"
              :loading="uploading"
              @click="startUpload"
            >
              {{ `上传中 (${progress}%)` }}
            </div>
            <el-alert
              v-if="errorMessage"
              :title="errorMessage"
              type="error"
              show-icon
              closable
              class="alert-message"
            />
            <el-row class="btn-group">
              <el-button
                style="
                  position: absolute;
                  top: -10px;
                  left: 10px;
                  font-size: 12px;
                  padding: 6px;
                "
                round
                type="warning"
                v-show="state == 'RUNNING'"
                @click="onPauseRecord()"
                >暂停</el-button
              >
              <el-button
                style="
                  position: absolute;
                  top: -10px;
                  left: -15px;
                  font-size: 12px;
                  padding: 6px;
                "
                round
                type="primary"
                v-show="state == 'PAUSE'"
                @click="onResumeRecord()"
                >继续录音</el-button
              >
              <el-button
                style="
                  position: absolute;
                  top: -10px;
                  left: 50px;
                  font-size: 12px;
                  padding: 6px;
                "
                round
                type="danger"
                v-show="state == 'RUNNING' || state == 'PAUSE'"
                @click="onCompleteRecord()"
              >
                结束</el-button
              >
              <el-button
                style="
                  position: absolute;
                  top: -10px;
                  left: -15px;
                  font-size: 12px;
                  padding: 6px;
                "
                round
                type="primary"
                v-show="state == 'COMPLETE'"
                @click="onRestartRecord()"
                >重新录音</el-button
              >
              <el-button
                style="
                  position: absolute;
                  top: -10px;
                  left: 55px;
                  font-size: 12px;
                  padding: 6px;
                "
                round
                type="primary"
                v-show="state == 'COMPLETE'"
                @click="onSendRecord()"
                >发送语音</el-button
              >
            </el-row>
          </div>
          <div
            style="
              padding: 10px 5px;
              display: flex;
              align-items: center;
              width: 100%;
            "
          >
            <div style="margin-left: 5px">
              <el-upload
                action="http://localhost:8080/files/upload"
                :show-file-list="false"
                :before-upload="handleFileChange"
              >
                <i
                  class="iconfont icon-lianjie"
                  style="font-size: 23px; color: gray"
                ></i>
              </el-upload>
            </div>
            <div title="发送语音" @click="onStartRecord()">
              <i
                class="iconfont icon-yuyin1"
                style="font-size: 25px; color: gray"
              ></i>
            </div>
            <div
              id="im-content"
              contenteditable
              style="
                flex: 1;
                background-color: #fff;
                margin: 0 5px;
                padding: 10px;
                border: 1px solid #e0e9ef;
                border-radius: 2px;
                outline: none;
                font-size: 14px;
              "
            ></div>
            <div
              type="primary"
              @click="send"
              style="border: none; border-radius: 100%"
            >
              <i
                class="iconfont icon-fasong1"
                style="font-size: 45px; color: #007bff"
              ></i>
            </div>
          </div>
        </div>
        <!--  中间部分结束  -->
      </div>
    </div>
  </div>
</template>

<script>
import request from "@/utils/request";
import Recorder from "js-audio-recorder";

let client;
export default {
  name: "chatRecord",
  props: {
    visible: {
      type: Boolean,
    },
  },
  data() {
    return {
      user: {},
      groups: [],
      permission: [],
      groupIdNow: "",
      messages: [],
      users: [],
      client: null, // ✅ 让 WebSocket 变量绑定到 Vue 实例
      groupName: "",

      showFriendModal: false,
      selectedFile: null,
      uploading: false,
      progress: 0,
      errorMessage: "",
      ws: null,
      uploadCancelToken: null,

      rc: null,
      audio: null,
      state: "STOP", // STOP、RUNNING、PAUSE、COMPLETE
      stateTip: "未开始",
      mode: "PLAY", // RECORD 、PLAY
      duration: 0,
      url: "",
    };
  },

  async mounted() {
    this.rc = new Recorder();
    this.audio = new Audio();
    // ✅ 1. 初始化 WebSocket 连接
    client = new WebSocket(`ws://localhost:8080/imserverSingle`);
    client.onopen = () => {
      console.log("websocket open");
    };
    client.onclose = () => {
      // 页面刷新的时候和后台websocket服务关闭的时候
      console.log("websocket close");
    };
    client.onmessage = (msg) => {
      if (msg.data) {
        let json = JSON.parse(msg.data);
        if (
          (json.content &&
            json.fromuser === this.fromUser &&
            json.touser === this.toUser) ||
          (json.touser === this.fromUser && json.fromuser === this.toUser)
        ) {
          // 聊天消息
          this.messages.push(json);
          this.scrollToBottom(); // 滚动页面到最底部
        }
      }
    };
    // this.load();

    // ✅ 2. 先加载群组数据，再加载聊天记录
    await this.getgroups();

    if (this.groups.length > 0 && this.groups[0].id) {
      this.groupName = this.groups[0].name;
      this.load(this.groups[0].id);
    } else {
      console.warn("未找到可用的群组数据");
    }

    // ✅ 3. 读取本地存储的用户数据
    this.user = JSON.parse(localStorage.getItem("user") || "{}");
  },

  beforeDestroy() {
    if (this.client) {
      this.client.close();
      console.log("WebSocket 连接已关闭");
    }
  },

  methods: {
    async getgroups() {
      try {
        const res = await request.get("/imGroup");
        if (res.code === "0" && Array.isArray(res.data)) {
          this.groups = res.data;
        } else {
          console.error("获取群组数据失败", res.msg);
        }
      } catch (error) {
        console.error("请求群组数据失败", error);
      }
    },

    async load(groupId, groupName) {
      if (!groupId) {
        console.error("groupId 为空，无法加载消息");
        return;
      }
      this.groupIdNow = groupId;
      this.groupName = groupName;
      try {
        console.log("加载群组消息，groupId:", groupId);
        const res = await request.get(`/imGroup/all/${groupId}`);

        if (res.code === "0" && Array.isArray(res.data)) {
          this.messages = res.data;
          this.$nextTick(() => this.scrollToBottom());
        } else {
          this.$message.error(res.msg || "加载消息失败");
        }
      } catch (error) {
        console.error("消息加载失败：", error);
        this.$message.error("网络错误，请稍后再试");
      }
    },

    download(file) {
      window.open(file);
    },
    handleFile(file) {
      if (client) {
        let message = {
          name: this.user.name,
          content: file.data,
          avatar: this.user.avatar,
        };
        let extName = file.data.substring(file.data.lastIndexOf(".") + 1);
        if (
          ["png", "jpg", "jpeg", "gif", "bmp", "tiff", "svg", "webp"].includes(
            extName
          )
        ) {
          message.type = "img";
        } else {
          message.type = "file";
        }
        client.send(JSON.stringify(message));
      }
    },

    send() {
      let inputBox = document.getElementById("im-content");
      let content = inputBox.textContent.trim(); // 使用 textContent 避免 XSS，去除首尾空格

      if (!content) {
        this.$notify.error("请输入聊天内容");
        return;
      }

      if (!client || client.readyState !== WebSocket.OPEN) {
        this.$notify.error("连接未建立，请稍后重试");
        return;
      }

      let message = {
        fromuser: this.user.name,
        content: content,
        type: "text",
        isToGroup: "1",
        fromavatar: this.user.avatar,
        time: new Date().getTime(),
        toGroupId: this.groupIdNow,
      };

      client.send(JSON.stringify(message));
      inputBox.textContent = ""; // 清空输入框内容

      this.load(this.groupIdNow).catch((err) => {
        console.error("加载聊天记录失败:", err);
        this.$notify.error("加载聊天记录失败");
      });
    },

    scrollToBottom() {
      this.$nextTick(() => {
        // 设置聊天滚动条到底部
        let imMessageBox = document.getElementsByClassName("im-message-box")[0];
        //设置滚动条到最底部
        imMessageBox.scrollTop = imMessageBox.scrollHeight;
      });
    },
    handleFileChange(file) {
      console.log("选中的文件:", file);
      this.selectedFile = file;
      this.startUpload(); // 选择文件后自动上传
    },

    async startUpload() {
      if (!this.selectedFile) {
        this.$message.error("请选择一个文件！");
        return;
      }

      this.uploading = true;
      this.errorMessage = "";
      this.progress = 0;

      try {
        this.initWebSocket(); // 初始化 WebSocket 连接

        // 创建 FormData
        const formData = new FormData();
        formData.append("file", this.selectedFile);

        // 发送文件上传请求
        request
          .post("/files/upload", formData, {
            headers: {
              "Content-Type": "multipart/form-data", // 确保 multipart 形式
            },
            onUploadProgress: (progressEvent) => {
              this.progress = Math.round(
                (progressEvent.loaded * 100) / progressEvent.total
              );
            },
          })
          .then((response) => {
            console.log("走完上传了");
            console.log(response);
            console.log(response.data);
            // 确保正确地从响应中提取 `fileUrl` 和 `flag`
            this.fileUrl = response.data.url || "";
            this.flag = response.data.flag || "";
            console.log("this.fileUrl=", this.fileUrl);
            console.log("this.flag=", this.flag);

            const message = this.getMessage("img");
            message.content = this.fileUrl;
            let extName = this.fileUrl.substring(
              this.fileUrl.lastIndexOf(".") + 1
            );
            if (
              [
                "png",
                "jpg",
                "jpeg",
                "gif",
                "bmp",
                "tiff",
                "svg",
                "webp",
              ].includes(extName)
            ) {
              message.type = "img";
            } else {
              message.type = "file";
            }
            client.send(JSON.stringify(message));

            if (!this.flag) {
              console.warn("上传成功，但未返回 flag，WebSocket 订阅可能失败！");
            }
          })
          .catch((error) => {
            console.error("上传失败:", error);
          });

        // 发送 WebSocket 消息
        if (this.ws && this.ws.readyState === WebSocket.OPEN) {
          // 订阅 WebSocket 进度
          client.send(
            JSON.stringify({
              action: "subscribe",
              flag: this.flag,
            })
          );
        } else {
          console.warn("WebSocket 未连接，无法发送文件消息");
        }

        this.handleUploadSuccess();
      } catch (err) {
        console.error("上传过程中发生错误:", err);
        this.handleError(err);
      } finally {
        this.uploading = false;
      }
    },

    initWebSocket() {
      const wsUrl = `ws://localhost:8080/progress`;
      this.ws = new WebSocket(wsUrl);

      console.log("尝试连接 WebSocket:", wsUrl);

      this.ws.onopen = () => {
        console.log("WebSocket 连接成功");
        if (!this.flag) {
          console.error("WebSocket 订阅失败：flag 为空");
          return;
        }
        console.log("发送订阅消息");
        this.ws.send(
          JSON.stringify({
            action: "subscribe",
            flag: this.flag,
          })
        );
        console.log("-------------");
      };

      this.ws.onerror = (error) => {
        console.error("WebSocket 错误详情:", error);
        console.log("错误事件对象:", error);
      };

      // this.ws.onclose = (event) => {
      //   console.log("连接关闭代码:", event.code, "原因:", event.reason);
      // };
    },

    cancelUpload() {
      if (this.uploadCancelToken) {
        this.uploadCancelToken("用户取消上传");
      }
      this.resetState();
      this.$message.warning("上传已取消");
    },

    handleUploadSuccess() {
      this.uploading = false;
      this.$message.success({
        message: "上传成功",
        duration: 2000,
        onClose: () => {
          this.resetState();
        },
      });
    },

    handleError(err) {
      console.error("上传失败:", err);
      this.errorMessage =
        err.response?.data?.error || err.message || "上传失败";
      this.uploading = false;
      this.closeWebSocket();
    },

    resetState() {
      this.selectedFile = null;
      this.progress = 0;
      this.uploading = false;
      this.closeWebSocket();
    },

    closeWebSocket() {
      if (this.ws) {
        this.ws.close();
        this.ws = null;
      }
    },
    // 语音功能
    onClose() {
      // 关闭前清除数据
      this.rc.destroy();
      this.rc = new Recorder();
      this.audio.pause();
      this.mode = "RECORD";
      this.state = "STOP";
      this.stateTip = "未开始";
      this.$emit("close");
    },
    onStartRecord() {
      console.log("开始录音ing");
      this.rc
        .start()
        .then((stream) => {
          console.log("录音开始成功");
          this.state = "RUNNING";
          this.stateTip = "正在录音...";
          console.log("正在录音...");
        })
        .catch((error) => {
          console.error("录音开始失败:", error);
          this.$message.error(error);
        });
    },
    onPauseRecord() {
      this.rc.pause();
      this.state = "PAUSE";
      this.stateTip = "已暂停录音";
      console.log("已暂停录音");
    },
    onResumeRecord() {
      this.rc.resume();
      this.state = "RUNNING";
      this.stateTip = "正在录音...";
      console.log("正在录音2...");
    },
    onCompleteRecord() {
      this.rc.pause();
      this.state = "COMPLETE";
      this.stateTip = "已结束录音";
      console.log("已结束录音");
    },
    onRestartRecord() {
      this.rc.destroy();
      this.rc = new Recorder();
      this.rc.start();
      this.state = "RUNNING";
      this.mode = "RECORD";
      this.stateTip = "正在录音...";
    },
    onSendRecord() {
      let wav = this.rc.getWAVBlob();
      console.log("录音 Blob:", wav);
      let name = new Date().getTime() + ".wav";
      var formData = new window.FormData();
      console.log("formData=", formData);

      this.initWebSocket(); // 初始化 WebSocket 连接
      formData.append("file", wav, name);
      console.log("formData=", formData);

      request
        .post("/files/uploadVoice", formData, {
          headers: {
            "Content-Type": "multipart/form-data",
          },
        })
        .then((res) => {
          console.log(res.data);
          const message = this.getMessage("img");
          message.content = res.data.url;
          this.url = res.data.url;
          message.type = "voice";
          console.log("message2=", message);
          client.send(JSON.stringify(message));
          this.onClose();
        });
    },
  },
};
</script>

<style scoped>
.im-message-box {
  font: 1.4em sans-serif;
  height: 434px;
  padding: 10px;
  overflow-y: auto;
  background-color: #f5faff;
}

.user-list-box {
  overflow-y: auto;
  padding: 10px;
  padding: 15px;
}

.user-list-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px;
  margin-bottom: 10px;
  background-color: #fff;
  border-radius: 8px;
  border: 1px solid #e0e9ef;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
  cursor: pointer;
  transition: background-color 0.3s ease;
}

.user-list-item:hover {
  background-color: #f5faff;
}

.im-message-box::-webkit-scrollbar,
.emoji-box::-webkit-scrollbar,
.user-list-box::-webkit-scrollbar {
  width: 4px;
}

.im-message-box::-webkit-scrollbar-thumb,
.emoji-box::-webkit-scrollbar-thumb,
.user-list-box::-webkit-scrollbar-thumb {
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.1);
}

.im-message-box::-webkit-scrollbar-track,
.user-list-box::-webkit-scrollbar-track {
  border-radius: 0;
  background: rgba(0, 0, 0, 0.1);
}

.im-message {
  font-size: 14px;
  padding: 10px;
  margin: 8px 0;
  border-radius: 5px;
  color: #000;
  max-width: 50%;
  line-height: 20px;
  width: fit-content;
}

.im-message-left {
  background-color: white;
  margin-left: 10px;
  border-radius: 20px;
}

.im-message-right {
  background-color: #3a8ee6;
  color: white;
  margin-right: 10px;
  border-radius: 20px;
}

.im-message-download {
  display: flex;
  align-items: center;
  padding: 8px;
  border-radius: 20px;
  cursor: pointer;
}

.user-list-item {
  padding: 10px;
  display: flex;
  align-items: center;
  border-bottom: 1px solid #eee;
  cursor: default;
  font-size: 14px;
}
.user-list-item:nth-last-child(1) {
  border: none;
}

.progress-bar {
  margin-top: 20px;
}

.alert-message {
  margin-top: 20px;
}
</style>
